package com.example.common.network;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.coszero.utilslibrary.app.AppManager;
import com.coszero.utilslibrary.app.AppUtils;
import com.coszero.utilslibrary.utils.LogX;
import com.coszero.utilslibrary.utils.PreferenceHelper;
import com.coszero.utilslibrary.utils.StringUtils;
import com.coszero.utilslibrary.utils.ToastUtils;
import com.example.common.config.Global;
import com.example.commonlib.R;

import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;

/**
 * Desc： 数据请求工具类
 *
 * @author xmqian
 * Email:xmqian93@163.com
 * Date: 2020/6/8 10:40
 * @version com.squareup.okhttp3:okhttp:4.2.2
 */
public class OkHttpUtils {
    private String TAG = "OkHttpUtils";
    private volatile static OkHttpUtils instance;

    private Handler handler;
    /**
     * 网络日志打印拦截器
     * 包含header、body数据
     * interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
     * setlevel用来设置日志打印的级别，共包括了四个级别：NONE,BASIC,HEADER,BODY
     * BASEIC:请求/响应行
     * HEADER:请求/响应行 + 头
     * BODY:请求/响应行 + 头 + 体
     */
    private HttpLoggingInterceptor interceptor =
            new HttpLoggingInterceptor(message -> {
                try {
                    Log.i(TAG, message);
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.e(TAG, message);
                }
            });
    private OkHttpClient.Builder builder;

    public OkHttpUtils() {
        handler = new Handler(Looper.getMainLooper());
    }

    private static OkHttpClient getUnsafeOkHttpClient() {
        try {
            // Create a trust manager that does not validate certificate chains
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                        }

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                        }

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[]{};
                        }
                    }
            };

            // Install the all-trusting trust manager
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            // Create an ssl socket factory with our all-trusting manager
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslSocketFactory);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });

            OkHttpClient okHttpClient = builder.build();
            return okHttpClient;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 单例模式
     *
     * @return
     */

    public static OkHttpUtils getInstance() {
        if (instance == null) {
            synchronized (OkHttpUtils.class) {
                if (instance == null) {
                    instance = new OkHttpUtils();
                }
            }
        }
        return instance;
    }

    /**
     * @return 返回okhttpClient
     */
    private OkHttpClient.Builder getOkHttpClient() {
        if (builder == null) {
            builder = new OkHttpClient.Builder();
            builder.connectTimeout(NetWorkConfig.REQ_TIMEOUT_SECOND, TimeUnit.SECONDS)
                    .readTimeout(NetWorkConfig.REQ_READ_TIMEOUT_SECOND, TimeUnit.SECONDS)
                    .retryOnConnectionFailure(true);
            if (Global.IS_DEBUG_VERSION) {
                interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                builder.addInterceptor(interceptor);
//            client.addInterceptor(new HttpInterceptorUtils().setLogMode(HttpInterceptorUtils.LogModel.BASIC));
            }
        }
        return builder;
    }

    /**
     * 普通get方式
     *
     * @param URL BaseUrl
     * @param httpCallBack 成功或者失败方法
     */
    public void get(String URL, Request.Builder builder, HttpCallBack httpCallBack) {
        if (httpCallBack == null) {
            throw new NullPointerException("httpCallBack is null");
        }
        System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");
        OkHttpClient.Builder client = getOkHttpClient();
        final Request.Builder request = builder;
        builder
                .url(URL)
                .addHeader("token", "");
        client.build().newCall(request.build()).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                onErrorResponse(e, httpCallBack);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String string = response.body().string();
                onSuccessResponse(string, httpCallBack);
            }
        });
    }

    /**
     * 普通post
     *
     * @param URL BaseUrl
     * @param json post的参数 json
     * @param httpCallBack
     * @deprecated
     */
    public void post(String URL, JSONObject json, HttpCallBack httpCallBack) {
        System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");
        if (httpCallBack == null) {
            throw new NullPointerException("httpCallBack is null");
        }

        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        RequestBody requestBody = RequestBody.create(JSON, String.valueOf(json));
    }

    public void post(String url, RequestBody requestBody, HttpCallBack httpCallBack) {
        Request.Builder builder = new Request.Builder();
        post(url, requestBody, builder, httpCallBack);
    }

    public void post(String URL, RequestBody requestBody, Request.Builder builder, HttpCallBack httpCallBack) {
        if (StringUtils.isEmpty(URL)) {
            return;
        }
        OkHttpClient.Builder client = getOkHttpClient();//content-type:text/html;charset=UTF-8

        /*if (Global.ISDEBUG) {
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            client.addInterceptor(interceptor);
//            client.addInterceptor(new HttpInterceptorUtils().setLogMode(HttpInterceptorUtils.LogModel.BASIC));
        }*/
        Request.Builder request = builder;//版本号,请求参数
        request
                .url(URL)
                .post(requestBody)
                .addHeader("token", "");

        client.build().newCall(request.build()).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                onErrorResponse(e, httpCallBack);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String string = response.body().string();
                onSuccessResponse(string, httpCallBack);
            }
        });
    }

    public void postMap(String URL, RequestBody requestBody, HttpCallBack httpCallBack) {
        if (StringUtils.isEmpty(URL)) {
            return;
        }
        OkHttpClient.Builder client = getOkHttpClient();//content-type:text/html;charset=UTF-8

        /*if (Global.ISDEBUG) {
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            client.addInterceptor(interceptor);
//            client.addInterceptor(new HttpInterceptorUtils().setLogMode(HttpInterceptorUtils.LogModel.BASIC));
        }*/
        final Request request = new Request.Builder()//版本号,请求参数
                .url(URL)
                .post(requestBody)
                .addHeader("token", "")
                .build();

        client.build().newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                onErrorResponse(e, httpCallBack);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String string = response.body().string();
                onSuccessResponse(string, httpCallBack);
            }
        });
    }

    /**
     * 上传文件post
     *
     * @param URL BaseUrl
     * @param httpCallBack
     */

    public void postFile(String URL, Request.Builder builder, File file, HttpCallBack httpCallBack) {

//        RequestBody requestBody = new MultipartBody.Builder()
//            .setType(MultipartBody.FORM)
//            .addFormDataPart("file", fileName,
//                RequestBody.create(MediaType.parse("multipart/form-data"), new File(filePath)))
//            .build();
//        OkHttpClient client = new OkHttpClient();//content-type:text/html;charset=UTF-8
//        final Request request = new Request.Builder()//版本号,请求参数
//            .url(URL)
//            .post(requestBody)
//            .addHeader("language", PreferencesHelper.find(Key.LANGUAGE, ""))
//            .addHeader("version", "1.0.0")
//            .addHeader("token", PreferencesHelper.find(Key.TOKEN, ""))
//            .build();
//        client.newCall(request).enqueue(new Callback() {
//            @Override
//            public void onFailure(Call call, IOException e) {
//                onErrorResponse(e, httpCallBack);
//            }
//
//            @Override
//            public void onResponse(Call call, Response response) throws IOException {
//                String string = response.body().string();
//                onSuccessResponse(string, httpCallBack);
//            }
//        });


        System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");
        if (httpCallBack == null) {
            throw new NullPointerException("httpCallBack is null");
        }

        MultipartBody.Builder requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM);

        OkHttpClient client = new OkHttpClient();//content-type:text/html;charset=UTF-8
        // MediaType.parse() 里面是上传的文件类型。
        RequestBody body = RequestBody.create(MediaType.parse("image/*"), file);

        // 参数分别为， 请求key ，文件名称 ， RequestBody
        requestBody.addFormDataPart("file", file.getName(), body);
        Request.Builder request = builder;//版本号,请求参数
        builder.url(URL)
                .post(requestBody.build())
                .addHeader("token", "");
        client.newCall(request.build()).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                onErrorResponse(e, httpCallBack);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String string = response.body().string();
                onSuccessResponse(string, httpCallBack);
            }
        });
    }

    /**
     * 多文件上传
     *
     * @param URL
     * @param localImage
     * @param httpCallBack
     */
    public void postFile(String URL, Request.Builder builder, List<String> localImage, HttpCallBack httpCallBack) {
        System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");
        if (httpCallBack == null) {
            throw new NullPointerException("httpCallBack is null");
        }

        MultipartBody.Builder requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM);

        OkHttpClient client = new OkHttpClient();//content-type:text/html;charset=UTF-8
        for (int i = 0; i < localImage.size(); i++) {
            File file = new File(localImage.get(i));
            // MediaType.parse() 里面是上传的文件类型。
            RequestBody body = RequestBody.create(MediaType.parse("image/*"), file);

            // 参数分别为， 请求key ，文件名称 ， RequestBody
            requestBody.addFormDataPart("file", file.getName(), body);
        }
        Request.Builder request = builder;//版本号,请求参数
        builder.url(URL)
                .post(requestBody.build())
                .addHeader("token", "");
        client.newCall(request.build()).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                onErrorResponse(e, httpCallBack);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String string = response.body().string();
                onSuccessResponse(string, httpCallBack);
            }
        });
    }

    /**
     * 回调接口
     */
    public interface HttpCallBack {
        void onSucceed(String result);

        void onFail(Exception result, String msg);
    }

    private void onSuccessResponse(final String result, final HttpCallBack httpCallBack) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    if (httpCallBack != null) {
                        httpCallBack.onSucceed(result);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    LogX.e("### onSuccessResponse", e.getMessage());
                }
            }
        });
    }

    private void onErrorResponse(final Exception result, final HttpCallBack httpCallBack) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    if (httpCallBack != null) {
                        httpCallBack.onFail(result, "");
                        if (result instanceof SocketTimeoutException) {
                            ToastUtils.showMsg(AppUtils.getString(AppManager.getAppManager().currentActivity(), R.string.toast_timeout_error));
                            return;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}
